package handlers

import (
	"encoding/json"
	"restaurant-system/config"
	"restaurant-system/internal/models"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

type CreateReviewRequest struct {
	OrderID uint     `json:"order_id" binding:"required"`
	DishID  uint     `json:"dish_id" binding:"required"`
	Rating  int      `json:"rating" binding:"required,min=1,max=5"`
	Content string   `json:"content"`
	Images  []string `json:"images"`
}

type ReplyReviewRequest struct {
	Reply string `json:"reply" binding:"required"`
}

// 创建评价
func CreateReview(c *gin.Context) {
	userID, _ := c.Get("userID")
	var req CreateReviewRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 验证订单是否属于该用户
	var order models.Order
	if err := config.DB.Where("id = ? AND user_id = ?", req.OrderID, userID).First(&order).Error; err != nil {
		c.JSON(400, gin.H{"error": "订单不存在或不属于当前用户"})
		return
	}

	// 验证菜品是否存在于订单中
	var orderItem models.OrderItem
	if err := config.DB.Where("order_id = ? AND dish_id = ?", req.OrderID, req.DishID).First(&orderItem).Error; err != nil {
		c.JSON(400, gin.H{"error": "该菜品不在订单中"})
		return
	}

	// 检查是否已经评价过
	var existingReview models.Review
	if err := config.DB.Where("order_id = ? AND dish_id = ?", req.OrderID, req.DishID).First(&existingReview).Error; err == nil {
		c.JSON(400, gin.H{"error": "该菜品已经评价过"})
		return
	}

	// 将图片数组转换为JSON字符串
	imagesJSON, _ := json.Marshal(req.Images)

	review := models.Review{
		UserID:  userID.(uint),
		OrderID: req.OrderID,
		DishID:  req.DishID,
		Rating:  req.Rating,
		Content: req.Content,
		Images:  string(imagesJSON),
	}

	if err := config.DB.Create(&review).Error; err != nil {
		c.JSON(500, gin.H{"error": "创建评价失败"})
		return
	}

	c.JSON(200, gin.H{
		"success": true,
		"message": "评价成功",
		"review":  review,
	})
}

// 商家回复评价
func ReplyReview(c *gin.Context) {
	id := c.Param("id")
	var req ReplyReviewRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	if err := config.DB.Model(&models.Review{}).Where("id = ?", id).
		Update("reply", req.Reply).Error; err != nil {
		c.JSON(500, gin.H{"error": "回复评价失败"})
		return
	}

	c.JSON(200, gin.H{"message": "回复成功"})
}

// 获取菜品的评价列表
func GetDishReviews(c *gin.Context) {
	dishID := c.Param("id")
	var reviews []models.Review

	// 使用 Preload 加载用户信息
	if err := config.DB.Preload("User").Where("dish_id = ?", dishID).Find(&reviews).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取评价列表失败"})
		return
	}

	// 处理每条评价的图片和用户信息
	type ReviewResponse struct {
		ID        uint      `json:"id"`
		UserID    uint      `json:"user_id"`
		Username  string    `json:"username"`
		Rating    int       `json:"rating"`
		Content   string    `json:"content"`
		Reply     string    `json:"reply"`
		Images    []string  `json:"images"`
		CreatedAt time.Time `json:"created_at"`
	}

	var response []ReviewResponse
	for _, review := range reviews {
		var images []string
		json.Unmarshal([]byte(review.Images), &images)

		resp := ReviewResponse{
			ID:        review.ID,
			UserID:    review.UserID,
			Username:  review.User.Username,
			Rating:    review.Rating,
			Content:   review.Content,
			Reply:     review.Reply,
			Images:    images,
			CreatedAt: review.CreatedAt,
		}
		response = append(response, resp)
	}

	c.JSON(200, gin.H{
		"reviews": response,
		"total":   len(response),
	})
}

// 获取用户的评价列表
func GetUserReviews(c *gin.Context) {
	userID, _ := c.Get("userID")
	var reviews []models.Review

	if err := config.DB.Where("user_id = ?", userID).Find(&reviews).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取评价列表失败"})
		return
	}

	// 处理每条评价的图片
	type ReviewResponse struct {
		models.Review
		Images []string `json:"images"`
	}

	var response []ReviewResponse
	for _, review := range reviews {
		var images []string
		json.Unmarshal([]byte(review.Images), &images)
		response = append(response, ReviewResponse{
			Review: review,
			Images: images,
		})
	}

	c.JSON(200, gin.H{"reviews": response})
}

// 获取所有评价（管理员接口）
func GetAllReviews(c *gin.Context) {
	// 获取分页参数
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
	
	var total int64
	var reviews []models.Review

	// 获取总数
	if err := config.DB.Model(&models.Review{}).Count(&total).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取评价总数失败"})
		return
	}

	// 查询所有评价，并预加载关联数据
	if err := config.DB.
		Preload("User").
		Preload("Dish").
		Order("created_at desc").
		Offset((page - 1) * pageSize).
		Limit(pageSize).
		Find(&reviews).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取评价列表失败"})
		return
	}

	// 处理每条评价的图片
	type ReviewResponse struct {
		ID       uint   `json:"id"`
		UserID   uint   `json:"user_id"`
		Username string `json:"username"`
		Dish     struct {
			ID       uint   `json:"id"`
			Name     string `json:"name"`
			ImageURL string `json:"image_url"`
		} `json:"Dish"`
		Rating    int       `json:"rating"`
		Content   string    `json:"content"`
		Reply     string    `json:"reply"`
		Images    []string  `json:"images"`
		CreatedAt time.Time `json:"created_at"`
	}

	var response []ReviewResponse
	for _, review := range reviews {
		var images []string
		json.Unmarshal([]byte(review.Images), &images)

		resp := ReviewResponse{
			ID:       review.ID,
			UserID:   review.UserID,
			Username: review.User.Username,
			Dish: struct {
				ID       uint   `json:"id"`
				Name     string `json:"name"`
				ImageURL string `json:"image_url"`
			}{
				ID:       review.Dish.ID,
				Name:     review.Dish.Name,
				ImageURL: review.Dish.ImageURL,
			},
			Rating:    review.Rating,
			Content:   review.Content,
			Reply:     review.Reply,
			Images:    images,
			CreatedAt: review.CreatedAt,
		}
		response = append(response, resp)
	}

	c.JSON(200, gin.H{
		"reviews": response,
		"total": total,
		"page": page,
		"pageSize": pageSize,
	})
}

func GetReviews(c *gin.Context) {
	var reviews []models.Review

	if err := config.DB.
		Preload("Dish").
		Order("created_at desc").
		Find(&reviews).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取评价列表失败"})
		return
	}

	c.JSON(200, gin.H{"reviews": reviews})
}
